﻿using HMS.TenantServer.Authentication.Abstractions;
using HMS.TenantServer.Entities;
using IdentityModel;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;

namespace HMS.TenantServer.Authentication.Jwt;

internal class JwtUserPool : UserPoolBase
{
    private readonly DbContext _context;
    private readonly ILogger<JwtUserPool> _logger;

    public JwtUserPool(DbContext context, ILogger<JwtUserPool> logger)
    {
        _context = context;
        _logger = logger;
    }

    public override async Task<(ICollection<Claim>? claims, Tenant? tenant)> ValidateAsync(bool isRoot, string account, string password)
    {
        Tenant? tenant = null;

        var name = string.Empty;

        if (isRoot)
        {
            tenant = await _context.Set<Tenant>().FirstOrDefaultAsync(x => x.RootAccount == account && x.Password == password);

            if (tenant is not null)
            {
                name = tenant.Name;
            }
        }
        else
        {
            var user = await _context.Set<User>().Include(x => x.Tenant).FirstOrDefaultAsync(n => n.Account == account && n.Password == password);

            if (user is not null)
            {
                tenant = user.Tenant;
                name = user.Name;
            }
        }

        if (tenant is not null)
        {
            var claims = new Claim[]
            {
                new Claim(JwtClaimTypes.Subject, tenant.Id.ToString()),
                new Claim(JwtClaimTypes.Name, account),
                new Claim(JwtClaimTypes.JwtId, Guid.NewGuid().ToString("N")),
                new Claim(JwtClaimTypes.IdentityProvider, "local"),
                new Claim(JwtClaimTypes.AuthenticationMethod, "pwd"),
                new Claim("tenant", tenant.TenantId),
                new Claim("tenant:license", tenant.License),
                new Claim("tenant:isroot", isRoot.ToString()),
            };

            _logger.LogInformation("用户：{account} 认证成功", name);

            return (claims, tenant);
        }

        return (null, null);
    }
}